home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / m6502 / ops02.h < prev    next >
C/C++ Source or Header  |  2000-05-08  |  25KB  |  744 lines

  1. /*****************************************************************************
  2.  *
  3.  *     ops02.h
  4.  *     Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs
  5.  *
  6.  *     Copyright (c) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
  7.  *     65sc02 core Copyright (c) 2000 Peter Trauner, all rights reserved.
  8.  *
  9.  *     - This source code is released as freeware for non-commercial purposes.
  10.  *     - You are free to use and redistribute this code in modified or
  11.  *       unmodified form, provided you list me in the credits.
  12.  *     - If you modify this source code, you must add a notice to each modified
  13.  *       source file that it has been changed.  If you're a nice person, you
  14.  *       will clearly mark each change too.  :)
  15.  *     - If you wish to use this for commercial purposes, please contact me at
  16.  *       pullmoll@t-online.de
  17.  *     - The author of this copywritten work reserves the right to change the
  18.  *       terms of its usage and license at any time, including retroactively
  19.  *     - This entire notice must remain in the source code.
  20.  *
  21.  *****************************************************************************/
  22.  
  23. /* 6502 flags */
  24. #define F_C 0x01
  25. #define F_Z 0x02
  26. #define F_I 0x04
  27. #define F_D 0x08
  28. #define F_B 0x10
  29. #define F_T 0x20
  30. #define F_V 0x40
  31. #define F_N 0x80
  32.  
  33. /* some shortcuts for improved readability */
  34. #define A    m6502.a
  35. #define X    m6502.x
  36. #define Y    m6502.y
  37. #define P    m6502.p
  38. #define S    m6502.sp.b.l
  39. #define SPD m6502.sp.d
  40.  
  41. #define NZ    m6502.nz
  42.  
  43. #define SET_NZ(n)                \
  44.     if ((n) == 0) P = (P & ~F_N) | F_Z; else P = (P & ~(F_N | F_Z)) | ((n) & F_N)
  45.  
  46. #define SET_Z(n)                \
  47.     if ((n) == 0) P |= F_Z; else P &= ~F_Z
  48.  
  49. #define EAL m6502.ea.b.l
  50. #define EAH m6502.ea.b.h
  51. #define EAW m6502.ea.w.l
  52. #define EAD m6502.ea.d
  53.  
  54. #define ZPL m6502.zp.b.l
  55. #define ZPH m6502.zp.b.h
  56. #define ZPW m6502.zp.w.l
  57. #define ZPD m6502.zp.d
  58.  
  59. #define PCL m6502.pc.b.l
  60. #define PCH m6502.pc.b.h
  61. #define PCW m6502.pc.w.l
  62. #define PCD m6502.pc.d
  63.  
  64. #define PPC m6502.ppc.d
  65.  
  66. #if FAST_MEMORY
  67. extern    MHELE    *cur_mwhard;
  68. extern    MHELE    *cur_mrhard;
  69. extern    UINT8    *RAM;
  70. #endif
  71.  
  72. #define CHANGE_PC change_pc16(PCD)
  73.  
  74. /***************************************************************
  75.  *    RDOP    read an opcode
  76.  ***************************************************************/
  77. #define RDOP() cpu_readop(PCW++)
  78.  
  79. /***************************************************************
  80.  *    RDOPARG read an opcode argument
  81.  ***************************************************************/
  82. #define RDOPARG() cpu_readop_arg(PCW++)
  83.  
  84. /***************************************************************
  85.  *    RDMEM    read memory
  86.  ***************************************************************/
  87. #if FAST_MEMORY
  88. #define RDMEM(addr)                                             \
  89.     ((cur_mrhard[(addr) >> (ABITS2_16 + ABITS_MIN_16)]) ?        \
  90.         cpu_readmem16(addr) : RAM[addr])
  91. #else
  92. #define RDMEM(addr) cpu_readmem16(addr)
  93. #endif
  94.  
  95. /***************************************************************
  96.  *    WRMEM    write memory
  97.  ***************************************************************/
  98. #if FAST_MEMORY
  99. #define WRMEM(addr,data)                                        \
  100.     if (cur_mwhard[(addr) >> (ABITS2_16 + ABITS_MIN_16)])        \
  101.         cpu_writemem16(addr,data);                                \
  102.     else                                                        \
  103.         RAM[addr] = data
  104. #else
  105. #define WRMEM(addr,data) cpu_writemem16(addr,data)
  106. #endif
  107.  
  108. /***************************************************************
  109.  *    BRA  branch relative
  110.  *    extra cycle if page boundary is crossed
  111.  ***************************************************************/
  112. #define BRA(cond)                                                \
  113.     if (cond)                                                    \
  114.     {                                                            \
  115.         tmp = RDOPARG();                                        \
  116.         EAW = PCW + (signed char)tmp;                            \
  117.         m6502_ICount -= (PCH == EAH) ? 3 : 4;                    \
  118.         PCD = EAD;                                                \
  119.         CHANGE_PC;                                                \
  120.     }                                                            \
  121.     else                                                        \
  122.     {                                                            \
  123.         PCW++;                                                    \
  124.         m6502_ICount -= 2;                                        \
  125.     }
  126.  
  127. /***************************************************************
  128.  *
  129.  * Helper macros to build the effective address
  130.  *
  131.  ***************************************************************/
  132.  
  133. /***************************************************************
  134.  *    EA = zero page address
  135.  ***************************************************************/
  136. #define EA_ZPG                                                    \
  137.     ZPL = RDOPARG();                                            \
  138.     EAD = ZPD
  139.  
  140. /***************************************************************
  141.  *    EA = zero page address + X
  142.  ***************************************************************/
  143. #define EA_ZPX                                                    \
  144.     ZPL = RDOPARG() + X;                                        \
  145.     EAD = ZPD
  146.  
  147. /***************************************************************
  148.  *    EA = zero page address + Y
  149.  ***************************************************************/
  150. #define EA_ZPY                                                    \
  151.     ZPL = RDOPARG() + Y;                                        \
  152.     EAD = ZPD
  153.  
  154. /***************************************************************
  155.  *    EA = absolute address
  156.  ***************************************************************/
  157. #define EA_ABS                                                    \
  158.     EAL = RDOPARG();                                            \
  159.     EAH = RDOPARG()
  160.  
  161. /***************************************************************
  162.  *    EA = absolute address + X
  163.  ***************************************************************/
  164. #define EA_ABX                                                    \
  165.     EA_ABS;                                                     \
  166.     EAW += X
  167.  
  168. /***************************************************************
  169.  *    EA = absolute address + Y
  170.  ***************************************************************/
  171. #define EA_ABY                                                    \
  172.     EA_ABS;                                                     \
  173.     EAW += Y
  174.  
  175. /***************************************************************
  176.  *    EA = zero page + X indirect (pre indexed)
  177.  ***************************************************************/
  178. #define EA_IDX                                                    \
  179.     ZPL = RDOPARG() + X;                                        \
  180.     EAL = RDMEM(ZPD);                                            \
  181.     ZPL++;                                                        \
  182.     EAH = RDMEM(ZPD)
  183.  
  184. /***************************************************************
  185.  *    EA = zero page indirect + Y (post indexed)
  186.  *    subtract 1 cycle if page boundary is crossed
  187.  ***************************************************************/
  188. #define EA_IDY                                                    \
  189.     ZPL = RDOPARG();                                            \
  190.     EAL = RDMEM(ZPD);                                            \
  191.     ZPL++;                                                        \
  192.     EAH = RDMEM(ZPD);                                            \
  193.     if (EAL + Y > 0xff)                                         \
  194.         m6502_ICount--;                                         \
  195.     EAW += Y
  196.  
  197. /***************************************************************
  198.  *    EA = indirect (only used by JMP)
  199.  ***************************************************************/
  200. #define EA_IND                                                    \
  201.     EA_ABS;                                                     \
  202.     tmp = RDMEM(EAD);                                            \
  203.     EAL++;    /* booby trap: stay in same page! ;-) */            \
  204.     EAH = RDMEM(EAD);                                            \
  205.     EAL = tmp
  206.  
  207. /* read a value into tmp */
  208. #define RD_IMM    tmp = RDOPARG()
  209. #define RD_ACC    tmp = A
  210. #define RD_ZPG    EA_ZPG; tmp = RDMEM(EAD)
  211. #define RD_ZPX    EA_ZPX; tmp = RDMEM(EAD)
  212. #define RD_ZPY    EA_ZPY; tmp = RDMEM(EAD)
  213. #define RD_ABS    EA_ABS; tmp = RDMEM(EAD)
  214. #define RD_ABX    EA_ABX; tmp = RDMEM(EAD)
  215. #define RD_ABY    EA_ABY; tmp = RDMEM(EAD)
  216. #define RD_ZPI    EA_ZPI; tmp = RDMEM(EAD)
  217. #define RD_IDX    EA_IDX; tmp = RDMEM(EAD)
  218. #define RD_IDY    EA_IDY; tmp = RDMEM(EAD)
  219.  
  220. /* write a value from tmp */
  221. #define WR_ZPG    EA_ZPG; WRMEM(EAD, tmp)
  222. #define WR_ZPX    EA_ZPX; WRMEM(EAD, tmp)
  223. #define WR_ZPY    EA_ZPY; WRMEM(EAD, tmp)
  224. #define WR_ABS    EA_ABS; WRMEM(EAD, tmp)
  225. #define WR_ABX    EA_ABX; WRMEM(EAD, tmp)
  226. #define WR_ABY    EA_ABY; WRMEM(EAD, tmp)
  227. #define WR_ZPI    EA_ZPI; WRMEM(EAD, tmp)
  228. #define WR_IDX    EA_IDX; WRMEM(EAD, tmp)
  229. #define WR_IDY    EA_IDY; WRMEM(EAD, tmp)
  230.  
  231. /* write back a value from tmp to the last EA */
  232. #define WB_ACC    A = (UINT8)tmp;
  233. #define WB_EA    WRMEM(EAD, tmp)
  234.  
  235. /***************************************************************
  236.  ***************************************************************
  237.  *            Macros to emulate the plain 6502 opcodes
  238.  ***************************************************************
  239.  ***************************************************************/
  240.  
  241. /***************************************************************
  242.  * push a register onto the stack
  243.  ***************************************************************/
  244. #define PUSH(Rg) WRMEM(SPD, Rg); S--
  245.  
  246. /***************************************************************
  247.  * pull a register from the stack
  248.  ***************************************************************/
  249. #define PULL(Rg) S++; Rg = RDMEM(SPD)
  250.  
  251. /* 6502 ********************************************************
  252.  *    ADC Add with carry
  253.  ***************************************************************/
  254. #define ADC                                                     \
  255.     if (P & F_D)                                                \
  256.     {                                                            \
  257.     int c = (P & F_C);                                            \
  258.     int lo = (A & 0x0f) + (tmp & 0x0f) + c;                     \
  259.     int hi = (A & 0xf0) + (tmp & 0xf0);                         \
  260.         P &= ~(F_V | F_C|F_N|F_Z);                                \
  261.         if (!((lo+hi)&0xff)) P|=F_Z;                            \
  262.         if (lo > 0x09)                                            \
  263.         {                                                        \
  264.             hi += 0x10;                                         \
  265.             lo += 0x06;                                         \
  266.         }                                                        \
  267.         if (hi&0x80) P|=F_N;                                    \
  268.         if (~(A^tmp) & (A^hi) & F_N)                            \
  269.             P |= F_V;                                            \
  270.         if (hi > 0x90)                                            \
  271.             hi += 0x60;                                         \
  272.         if (hi & 0xff00)                                        \
  273.             P |= F_C;                                            \
  274.         A = (lo & 0x0f) + (hi & 0xf0);                            \
  275.     }                                                            \
  276.     else                                                        \
  277.     {                                                            \
  278.         int c = (P & F_C);                                        \
  279.         int sum = A + tmp + c;                                    \
  280.         P &= ~(F_V | F_C);                                        \
  281.         if (~(A^tmp) & (A^sum) & F_N)                            \
  282.             P |= F_V;                                            \
  283.         if (sum & 0xff00)                                        \
  284.             P |= F_C;                                            \
  285.         A = (UINT8) sum;                                        \
  286.         SET_NZ(A); \
  287.     }                                                            
  288.  
  289. /* 6502 ********************************************************
  290.  *    AND Logical and
  291.  ***************************************************************/
  292. #define AND                                                     \
  293.     A = (UINT8)(A & tmp);                                        \
  294.     SET_NZ(A)
  295.  
  296. /* 6502 ********************************************************
  297.  *    ASL Arithmetic shift left
  298.  ***************************************************************/
  299. #define ASL                                                     \
  300.     P = (P & ~F_C) | ((tmp >> 7) & F_C);                        \
  301.     tmp = (UINT8)(tmp << 1);                                    \
  302.     SET_NZ(tmp)
  303.  
  304. /* 6502 ********************************************************
  305.  *    BCC Branch if carry clear
  306.  ***************************************************************/
  307. #define BCC BRA(!(P & F_C))
  308.  
  309. /* 6502 ********************************************************
  310.  *    BCS Branch if carry set
  311.  ***************************************************************/
  312. #define BCS BRA(P & F_C)
  313.  
  314. /* 6502 ********************************************************
  315.  *    BEQ Branch if equal
  316.  ***************************************************************/
  317. #define BEQ BRA(P & F_Z)
  318.  
  319. /* 6502 ********************************************************
  320.  *    BIT Bit test
  321.  ***************************************************************/
  322. #define BIT                                                     \
  323.     P &= ~(F_N|F_V|F_Z);                                        \
  324.     P |= tmp & (F_N|F_V);                                        \
  325.     if ((tmp & A) == 0)                                         \
  326.         P |= F_Z
  327.  
  328. /* 6502 ********************************************************
  329.  *    BMI Branch if minus
  330.  ***************************************************************/
  331. #define BMI BRA(P & F_N)
  332.  
  333. /* 6502 ********************************************************
  334.  *    BNE Branch if not equal
  335.  ***************************************************************/
  336. #define BNE BRA(!(P & F_Z))
  337.  
  338. /* 6502 ********************************************************
  339.  *    BPL Branch if plus
  340.  ***************************************************************/
  341. #define BPL BRA(!(P & F_N))
  342.  
  343. /* 6502 ********************************************************
  344.  *    BRK Break
  345.  *    increment PC, push PC hi, PC lo, flags (with B bit set),
  346.  *    set I flag, jump via IRQ vector
  347.  ***************************************************************/
  348. #define BRK                                                     \
  349.     PCW++;                                                        \
  350.     PUSH(PCH);                                                    \
  351.     PUSH(PCL);                                                    \
  352.     PUSH(P | F_B);                                                \
  353.     P = (P | F_I);                                                \
  354.     PCL = RDMEM(M6502_IRQ_VEC);                                 \
  355.     PCH = RDMEM(M6502_IRQ_VEC+1);                                \
  356.     CHANGE_PC
  357.  
  358. /* 6502 ********************************************************
  359.  * BVC    Branch if overflow clear
  360.  ***************************************************************/
  361. #define BVC BRA(!(P & F_V))
  362.  
  363. /* 6502 ********************************************************
  364.  * BVS    Branch if overflow set
  365.  ***************************************************************/
  366. #define BVS BRA(P & F_V)
  367.  
  368. /* 6502 ********************************************************
  369.  * CLC    Clear carry flag
  370.  ***************************************************************/
  371. #define CLC                                                     \
  372.     P &= ~F_C
  373.  
  374. /* 6502 ********************************************************
  375.  * CLD    Clear decimal flag
  376.  ***************************************************************/
  377. #define CLD                                                     \
  378.     P &= ~F_D
  379.  
  380. /* 6502 ********************************************************
  381.  * CLI    Clear interrupt flag
  382.  ***************************************************************/
  383. #define CLI                                                     \
  384.     if ((m6502.irq_state != CLEAR_LINE) && (P & F_I)) {         \
  385.         logerror("M6502#%d CLI sets after_cli\n",cpu_getactivecpu()); \
  386.         m6502.after_cli = 1;                                    \
  387.     }                                                            \
  388.     P &= ~F_I
  389.  
  390. /* 6502 ********************************************************
  391.  * CLV    Clear overflow flag
  392.  ***************************************************************/
  393. #define CLV                                                     \
  394.     P &= ~F_V
  395.  
  396. /* 6502 ********************************************************
  397.  *    CMP Compare accumulator
  398.  ***************************************************************/
  399. #define CMP                                                     \
  400.     P &= ~F_C;                                                    \
  401.     if (A >= tmp)                                                \
  402.         P |= F_C;                                                \
  403.     SET_NZ((UINT8)(A - tmp))
  404.  
  405. /* 6502 ********************************************************
  406.  *    CPX Compare index X
  407.  ***************************************************************/
  408. #define CPX                                                     \
  409.     P &= ~F_C;                                                    \
  410.     if (X >= tmp)                                                \
  411.         P |= F_C;                                                \
  412.     SET_NZ((UINT8)(X - tmp))
  413.  
  414. /* 6502 ********************************************************
  415.  *    CPY Compare index Y
  416.  ***************************************************************/
  417. #define CPY                                                     \
  418.     P &= ~F_C;                                                    \
  419.     if (Y >= tmp)                                                \
  420.         P |= F_C;                                                \
  421.     SET_NZ((UINT8)(Y - tmp))
  422.  
  423. /* 6502 ********************************************************
  424.  *    DEC Decrement memory
  425.  ***************************************************************/
  426. #define DEC                                                     \
  427.     tmp = (UINT8)--tmp;                                         \
  428.     SET_NZ(tmp)
  429.  
  430. /* 6502 ********************************************************
  431.  *    DEX Decrement index X
  432.  ***************************************************************/
  433. #define DEX                                                     \
  434.     X = (UINT8)--X;                                             \
  435.     SET_NZ(X)
  436.  
  437. /* 6502 ********************************************************
  438.  *    DEY Decrement index Y
  439.  ***************************************************************/
  440. #define DEY                                                     \
  441.     Y = (UINT8)--Y;                                             \
  442.     SET_NZ(Y)
  443.  
  444. /* 6502 ********************************************************
  445.  *    EOR Logical exclusive or
  446.  ***************************************************************/
  447. #define EOR                                                     \
  448.     A = (UINT8)(A ^ tmp);                                        \
  449.     SET_NZ(A)
  450.  
  451. /* 6502 ********************************************************
  452.  *    ILL Illegal opcode
  453.  ***************************************************************/
  454. #define ILL                                                     \
  455.     logerror("M6502 illegal opcode %04x: %02x\n",(PCW-1)&0xffff, cpu_readop((PCW-1)&0xffff))
  456.  
  457. /* 6502 ********************************************************
  458.  *    INC Increment memory
  459.  ***************************************************************/
  460. #define INC                                                     \
  461.     tmp = (UINT8)++tmp;                                         \
  462.     SET_NZ(tmp)
  463.  
  464. /* 6502 ********************************************************
  465.  *    INX Increment index X
  466.  ***************************************************************/
  467. #define INX                                                     \
  468.     X = (UINT8)++X;                                             \
  469.     SET_NZ(X)
  470.  
  471. /* 6502 ********************************************************
  472.  *    INY Increment index Y
  473.  ***************************************************************/
  474. #define INY                                                     \
  475.     Y = (UINT8)++Y;                                             \
  476.     SET_NZ(Y)
  477.  
  478. /* 6502 ********************************************************
  479.  *    JMP Jump to address
  480.  *    set PC to the effective address
  481.  ***************************************************************/
  482. #define JMP                                                     \
  483.     if( EAD == PPC && !m6502.pending_irq && !m6502.after_cli )    \
  484.         if( m6502_ICount > 0 ) m6502_ICount = 0;                \
  485.     PCD = EAD;                                                    \
  486.     CHANGE_PC
  487.  
  488. /* 6502 ********************************************************
  489.  *    JSR Jump to subroutine
  490.  *    decrement PC (sic!) push PC hi, push PC lo and set
  491.  *    PC to the effective address
  492.  ***************************************************************/
  493. #define JSR                                                     \
  494.     EAL = RDOPARG();                                            \
  495.     PUSH(PCH);                                                    \
  496.     PUSH(PCL);                                                    \
  497.     EAH = RDOPARG();                                            \
  498.     PCD = EAD;                                                    \
  499.     CHANGE_PC
  500.  
  501. /* 6502 ********************************************************
  502.  *    LDA Load accumulator
  503.  ***************************************************************/
  504. #define LDA                                                     \
  505.     A = (UINT8)tmp;                                             \
  506.     SET_NZ(A)
  507.  
  508. /* 6502 ********************************************************
  509.  *    LDX Load index X
  510.  ***************************************************************/
  511. #define LDX                                                     \
  512.     X = (UINT8)tmp;                                             \
  513.     SET_NZ(X)
  514.  
  515. /* 6502 ********************************************************
  516.  *    LDY Load index Y
  517.  ***************************************************************/
  518. #define LDY                                                     \
  519.     Y = (UINT8)tmp;                                             \
  520.     SET_NZ(Y)
  521.  
  522. /* 6502 ********************************************************
  523.  *    LSR Logic shift right
  524.  *    0 -> [7][6][5][4][3][2][1][0] -> C
  525.  ***************************************************************/
  526. #define LSR                                                     \
  527.     P = (P & ~F_C) | (tmp & F_C);                                \
  528.     tmp = (UINT8)tmp >> 1;                                        \
  529.     SET_NZ(tmp)
  530.  
  531. /* 6502 ********************************************************
  532.  *    NOP No operation
  533.  ***************************************************************/
  534. #define NOP
  535.  
  536. /* 6502 ********************************************************
  537.  *    ORA Logical inclusive or
  538.  ***************************************************************/
  539. #define ORA                                                     \
  540.     A = (UINT8)(A | tmp);                                        \
  541.     SET_NZ(A)
  542.  
  543. /* 6502 ********************************************************
  544.  *    PHA Push accumulator
  545.  ***************************************************************/
  546. #define PHA                                                     \
  547.     PUSH(A)
  548.  
  549. /* 6502 ********************************************************
  550.  *    PHP Push processor status (flags)
  551.  ***************************************************************/
  552. #define PHP                                                     \
  553.     PUSH(P)
  554.  
  555. /* 6502 ********************************************************
  556.  *    PLA Pull accumulator
  557.  ***************************************************************/
  558. #define PLA                                                     \
  559.     PULL(A);                                                    \
  560.     SET_NZ(A)
  561.  
  562.  
  563. /* 6502 ********************************************************
  564.  *    PLP Pull processor status (flags)
  565.  ***************************************************************/
  566. #define PLP                                                     \
  567.     if ( P & F_I ) {                                            \
  568.         PULL(P);                                                \
  569.         if ((m6502.irq_state != CLEAR_LINE) && !(P & F_I)) {    \
  570.             LOG(("M6502#%d PLP sets after_cli\n",cpu_getactivecpu())); \
  571.             m6502.after_cli = 1;                                \
  572.         }                                                        \
  573.     } else {                                                    \
  574.         PULL(P);                                                \
  575.     }                                                            \
  576.     P |= (F_T|F_B);
  577.  
  578. /* 6502 ********************************************************
  579.  * ROL    Rotate left
  580.  *    new C <- [7][6][5][4][3][2][1][0] <- C
  581.  ***************************************************************/
  582. #define ROL                                                     \
  583.     tmp = (tmp << 1) | (P & F_C);                                \
  584.     P = (P & ~F_C) | ((tmp >> 8) & F_C);                        \
  585.     tmp = (UINT8)tmp;                                            \
  586.     SET_NZ(tmp)
  587.  
  588. /* 6502 ********************************************************
  589.  * ROR    Rotate right
  590.  *    C -> [7][6][5][4][3][2][1][0] -> new C
  591.  ***************************************************************/
  592. #define ROR                                                     \
  593.     tmp |= (P & F_C) << 8;                                        \
  594.     P = (P & ~F_C) | (tmp & F_C);                                \
  595.     tmp = (UINT8)(tmp >> 1);                                    \
  596.     SET_NZ(tmp)
  597.  
  598. /* 6502 ********************************************************
  599.  * RTI    Return from interrupt
  600.  * pull flags, pull PC lo, pull PC hi and increment PC
  601.  *    PCW++;
  602.  ***************************************************************/
  603. #define RTI                                                     \
  604.     PULL(P);                                                    \
  605.     PULL(PCL);                                                    \
  606.     PULL(PCH);                                                    \
  607.     P |= F_T | F_B;                                             \
  608.     if( (m6502.irq_state != CLEAR_LINE) && !(P & F_I) )         \
  609.     {                                                            \
  610.         LOG(("M6502#%d RTI sets after_cli\n",cpu_getactivecpu())); \
  611.         m6502.after_cli = 1;                                    \
  612.     }                                                            \
  613.     CHANGE_PC
  614.  
  615. /* 6502 ********************************************************
  616.  *    RTS Return from subroutine
  617.  *    pull PC lo, PC hi and increment PC
  618.  ***************************************************************/
  619. #define RTS                                                     \
  620.     PULL(PCL);                                                    \
  621.     PULL(PCH);                                                    \
  622.     PCW++;                                                        \
  623.     CHANGE_PC
  624.  
  625. /* 6502 ********************************************************
  626.  *    SBC Subtract with carry
  627.  ***************************************************************/
  628. #define SBC                                                     \
  629.     if (P & F_D)                                                \
  630.     {                                                            \
  631.         int c = (P & F_C) ^ F_C;                                \
  632.         int sum = A - tmp - c;                                    \
  633.         int lo = (A & 0x0f) - (tmp & 0x0f) - c;                 \
  634.         int hi = (A & 0xf0) - (tmp & 0xf0);                     \
  635.         if (lo & 0x10)                                            \
  636.         {                                                        \
  637.             lo -= 6;                                            \
  638.             hi--;                                                \
  639.         }                                                        \
  640.         P &= ~(F_V | F_C|F_Z|F_N);                                \
  641.         if( (A^tmp) & (A^sum) & F_N )                            \
  642.             P |= F_V;                                            \
  643.         if( hi & 0x0100 )                                        \
  644.             hi -= 0x60;                                         \
  645.         if( (sum & 0xff00) == 0 )                                \
  646.             P |= F_C;                                            \
  647.         if( !((A-tmp-c) & 0xff) )                                \
  648.             P |= F_Z;                                            \
  649.         if( (A-tmp-c) & 0x80 )                                    \
  650.             P |= F_N;                                            \
  651.         A = (lo & 0x0f) | (hi & 0xf0);                            \
  652.     }                                                            \
  653.     else                                                        \
  654.     {                                                            \
  655.         int c = (P & F_C) ^ F_C;                                \
  656.         int sum = A - tmp - c;                                    \
  657.         P &= ~(F_V | F_C);                                        \
  658.         if( (A^tmp) & (A^sum) & F_N )                            \
  659.             P |= F_V;                                            \
  660.         if( (sum & 0xff00) == 0 )                                \
  661.             P |= F_C;                                            \
  662.         A = (UINT8) sum;                                        \
  663.         SET_NZ(A);                                                \
  664.     }                                                            
  665.  
  666. /* 6502 ********************************************************
  667.  *    SEC Set carry flag
  668.  ***************************************************************/
  669. #define SEC                                                     \
  670.     P |= F_C
  671.  
  672. /* 6502 ********************************************************
  673.  *    SED Set decimal flag
  674.  ***************************************************************/
  675. #define SED                                                     \
  676.     P |= F_D
  677.  
  678. /* 6502 ********************************************************
  679.  *    SEI Set interrupt flag
  680.  ***************************************************************/
  681. #define SEI                                                     \
  682.     P |= F_I
  683.  
  684. /* 6502 ********************************************************
  685.  * STA    Store accumulator
  686.  ***************************************************************/
  687. #define STA                                                     \
  688.     tmp = A
  689.  
  690. /* 6502 ********************************************************
  691.  * STX    Store index X
  692.  ***************************************************************/
  693. #define STX                                                     \
  694.     tmp = X
  695.  
  696. /* 6502 ********************************************************
  697.  * STY    Store index Y
  698.  ***************************************************************/
  699. #define STY                                                     \
  700.     tmp = Y
  701.  
  702. /* 6502 ********************************************************
  703.  * TAX    Transfer accumulator to index X
  704.  ***************************************************************/
  705. #define TAX                                                     \
  706.     X = A;                                                        \
  707.     SET_NZ(X)
  708.  
  709. /* 6502 ********************************************************
  710.  * TAY    Transfer accumulator to index Y
  711.  ***************************************************************/
  712. #define TAY                                                     \
  713.     Y = A;                                                        \
  714.     SET_NZ(Y)
  715.  
  716. /* 6502 ********************************************************
  717.  * TSX    Transfer stack LSB to index X
  718.  ***************************************************************/
  719. #define TSX                                                     \
  720.     X = S;                                                        \
  721.     SET_NZ(X)
  722.  
  723. /* 6502 ********************************************************
  724.  * TXA    Transfer index X to accumulator
  725.  ***************************************************************/
  726. #define TXA                                                     \
  727.     A = X;                                                        \
  728.     SET_NZ(A)
  729.  
  730. /* 6502 ********************************************************
  731.  * TXS    Transfer index X to stack LSB
  732.  * no flags changed (sic!)
  733.  ***************************************************************/
  734. #define TXS                                                     \
  735.     S = X
  736.  
  737. /* 6502 ********************************************************
  738.  * TYA    Transfer index Y to accumulator
  739.  ***************************************************************/
  740. #define TYA                                                     \
  741.     A = Y;                                                        \
  742.     SET_NZ(A)
  743.  
  744.